package com.gitee.wsl.data.observer


/**
 * An event resulting from a mutative [Cache] operation.
 */
 sealed interface DataChangeEvent<Key , Value> {
     val key: Key

     class Created<Key , Value >(
        override val key: Key,
         val value: Value,
    ) : DataChangeEvent<Key, Value> {
        override fun toString(): String {
            return "Created(key=$key, value=$value)"
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other == null || this::class != other::class) return false

            other as Created<*, *>

            return key == other.key && value == other.value
        }

        override fun hashCode(): Int {
            var result = key.hashCode()
            result = 31 * result + value.hashCode()
            return result
        }
    }

     class Updated<Key , Value >(
        override val key: Key,
         val oldValue: Value,
         val newValue: Value,
    ) : DataChangeEvent<Key, Value> {
        override fun toString(): String {
            return "Updated(key=$key, oldValue=$oldValue, newValue=$newValue)"
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other == null || this::class != other::class) return false

            other as Updated<*, *>

            return key == other.key && oldValue == other.oldValue && newValue == other.newValue
        }

        override fun hashCode(): Int {
            var result = key.hashCode()
            result = 31 * result + oldValue.hashCode()
            result = 31 * result + newValue.hashCode()
            return result
        }
    }

     class Removed<Key, Value>(
        override val key: Key,
         val value: Value,
    ) : DataChangeEvent<Key, Value> {
        override fun toString(): String {
            return "Removed(key=$key, value=$value)"
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other == null || this::class != other::class) return false

            other as Removed<*, *>

            return key == other.key && value == other.value
        }

        override fun hashCode(): Int {
            var result = key.hashCode()
            result = 31 * result + value.hashCode()
            return result
        }
    }

     class Expired<Key, Value>(
        override val key: Key,
         val value: Value,
    ) : DataChangeEvent<Key, Value> {
        override fun toString(): String {
            return "Expired(key=$key, value=$value)"
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other == null || this::class != other::class) return false

            other as Expired<*, *>

            return key == other.key && value == other.value
        }

        override fun hashCode(): Int {
            var result = key.hashCode()
            result = 31 * result + value.hashCode()
            return result
        }
    }

     class Evicted<Key, Value>(
        override val key: Key,
         val value: Value,
    ) : DataChangeEvent<Key, Value> {
        override fun toString(): String {
            return "Evicted(key=$key, value=$value)"
        }

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (other == null || this::class != other::class) return false

            other as Evicted<*, *>

            return key == other.key && value == other.value
        }

        override fun hashCode(): Int {
            var result = key.hashCode()
            result = 31 * result + value.hashCode()
            return result
        }
    }
}


fun<Key , Value, R> DataChangeEvent<Key , Value>.map( valueMap:(Value)->R): DataChangeEvent<Key, R> {
    return when(this){
        is DataChangeEvent.Created<Key, Value> -> DataChangeEvent.Created(key,valueMap(value))
        is DataChangeEvent.Evicted<Key, Value> -> DataChangeEvent.Evicted(key,valueMap(value ))
        is DataChangeEvent.Expired<Key, Value> -> DataChangeEvent.Expired(key,valueMap(value ))
        is DataChangeEvent.Removed<Key, Value> -> DataChangeEvent.Removed(key,valueMap(value ))
        is DataChangeEvent.Updated<Key, Value> -> DataChangeEvent.Updated(key,valueMap(oldValue),valueMap(newValue))
    }
}
